/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package solitaireofdoom.solitaire;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.swing.*;
import javax.swing.JMenuItem.*;
import java.awt.event.*;
import java.io.File;

import solitaireofdoom.klondike.*;
import solitaireofdoom.freecell.*;

/**
 * The SolitaireFrame is the basic frame of the application. It displays a menu, keeps track of highscores and notifiesthe user when he has completed a game.
 * 
 * @author Administrator
 */
public class SolitaireFrame extends JFrame
{
    private BufferedImage cards;
    public SolitaireType[] solitaireTypes;
    private Container con;

    public SolitaireFrame()
    {
        super("Solitaire");
        this.setLayout(null);
        this.setSize(400,400);
        this.setMaximumSize(new Dimension(this.getWidth(), this.getHeight()));
        this.setMinimumSize(new Dimension(this.getWidth(), this.getHeight()));

        // Ask if the game should be saved. 
        this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        this.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent we)
                {
                    for (int i = 0; i < SolitaireFrame.this.solitaireTypes.length; i++)
                    {
                        if (SolitaireFrame.this.solitaireTypes[i].isVisible())
                        {
                            int saveGame = JOptionPane.showConfirmDialog(null, "Do you want to save the game?", "Save the game?", JOptionPane.YES_NO_OPTION);
                            
                            if (saveGame == 0)
                                SolitaireFrame.this.solitaireTypes[i].saveGame();
                        }
                    }

                    System.exit(0);
                }
        });

        try
        {
            this.cards = javax.imageio.ImageIO.read(new File(System.getProperty("user.dir") + "\\cards.png"));
        }
        catch (Exception e)
        {
            
        }

        con = this.getContentPane();
        con.setBackground(new Color(0, 128, 0));

        // Create games
        solitaireTypes = new SolitaireType[2];
        solitaireTypes[0] = new Klondike(this, cards);
        solitaireTypes[1] = new Freecell(this, cards);

        // Create the manu
        JMenuBar theBar = new JMenuBar();

        JMenu gamesMenu = new JMenu("Games");
        JMenu rulesMenu = new JMenu("Rules");
        gamesMenu.setMnemonic(KeyEvent.VK_G);
        rulesMenu.setMnemonic(KeyEvent.VK_R);

        SolitaireFrameActionListener sfal = new SolitaireFrameActionListener();
        
        // Set default values for solitaireTypes
        for (int i = 0; i < solitaireTypes.length; i++)
        {
            String name = "Generic";
            if (solitaireTypes[i] instanceof Klondike)
                name = ((Klondike)solitaireTypes[i]).name;
            else if (solitaireTypes[i] instanceof Freecell)
                name = ((Freecell)solitaireTypes[i]).name;

            solitaireTypes[i].setLocation(10, 10);
            solitaireTypes[i].setVisible(false);
            con.add(solitaireTypes[i]);

            JMenu subMenu = new JMenu(name);
            subMenu.setMnemonic(name.charAt(0));
            
            JMenuItem newGame = new JMenuItem("New Game");
            newGame.setName(name + "game");
            newGame.setMnemonic(KeyEvent.VK_N);
            newGame.addActionListener(sfal);
            subMenu.add(newGame);

            JMenuItem loadGame = new JMenuItem("Load Game");
            loadGame.setName(name + "load");
            loadGame.setMnemonic(KeyEvent.VK_L);
            loadGame.addActionListener(sfal);
            subMenu.add(loadGame);

            JMenuItem highScore = new JMenuItem("High Score");
            highScore.setName(name + "high");
            highScore.setMnemonic(KeyEvent.VK_H);
            highScore.addActionListener(sfal);
            subMenu.add(highScore);

            gamesMenu.add(subMenu);

            JMenuItem ruleItem = new JMenuItem(name);
            ruleItem.setName(name + "rules");
            ruleItem.addActionListener(sfal);

            rulesMenu.add(ruleItem);
        }

        theBar.add(gamesMenu);
        theBar.add(rulesMenu);

        JMenu helpMenu = new JMenu("Help");

        JMenuItem showHint = new JMenuItem("Show hint");
        showHint.setName("hint");
        showHint.setMnemonic(KeyEvent.VK_H);
        showHint.addActionListener(sfal);
        helpMenu.add(showHint);

        JMenuItem aboutBox = new JMenuItem("About solitaire-of-doom");
        aboutBox.setName("about");
        aboutBox.setMnemonic(KeyEvent.VK_A);
        aboutBox.addActionListener(sfal);
        helpMenu.add(aboutBox);

        theBar.add(helpMenu);

        this.setJMenuBar(theBar);
        setVisible(true);
    }

    /**
     * This is called from the solitairetypes when a game has finished, for better or worse
     * @param type
     * @param time
     */
    public void gameFinished(SolitaireType type, int time)
    {
        // Lost game
        if (time == -1)
        {
            JOptionPane.showMessageDialog(this, "You have lost the game!");
            
            if (type instanceof Klondike)
                ((Klondike)type).newGame();
            else if (type instanceof Freecell)
                ((Freecell)type).newGame();
        }
        // Won game
        else
        {
            String gameName = "";
            if (type instanceof Klondike)
                gameName = ((Klondike)type).name;
            else if (type instanceof Freecell)
                gameName = ((Freecell)type).name;

            File f = new File(System.getProperty("user.dir") + "\\" + gameName + "high.txt");

            // Check if time is top 10
            int no10 = -1;
            String[] lines = new String[10];
            int c = 0;
            try
            {
                if (!f.exists())
                    f.createNewFile();

                BufferedReader reader = new BufferedReader(new FileReader(f));

                String line = null;
                while ((line = reader.readLine()) != null && c < 10)
                {
                    if (line.indexOf("\t") > -1)
                    {
                        lines[c] = line;
                        c++;
                    }
                }

                if (c > 0)
                {
                    String[] info = lines[c - 1].split("\t");
                    no10 = Integer.parseInt(info[1]);
                }
            }
            catch (FileNotFoundException exc) {  }
            catch (IOException exc) {  }
            c--;

            // If there hasn't been any other highscores
            if (no10 == -1)
            {
                String message = "";
                message += "You have won the game!\n";
                message += "It took only " + (int)Math.floor(time / 60) + " minutes and " + (time % 60) + " seconds. \n";
                message += "What is your name? (for the highscore list)";

                String name = JOptionPane.showInputDialog(this, message, "You won the game!", JOptionPane.PLAIN_MESSAGE);

                try
                {
                    if (!f.exists())
                        f.createNewFile();

                    BufferedWriter writer = new BufferedWriter(new FileWriter(f));

                    writer.write(name + "\t" + time + "\n");

                    writer.flush();
                    writer.close();
                }
                catch (Exception exc) {  }
            }
            // If the time is above the worst top 10 score
            else if (time < no10 || c != 9)
            {
                // Highscore index
                int h;
                String[] info = new String[2];
                for (h = 0; h < lines.length; h++)
                {
                    if (lines[h] == null)
                        break;
                    
                    info = lines[h].split("\t");
                    if (time < Integer.parseInt(info[1]))
                        break;
                }

                String message = "";
                message += "You have won the game!\n";
                message += "It took only " + (int)Math.floor(time / 60) + " minutes and " + (time % 60) + " seconds. \n";
                if (info[0] != null || info[1] != null)
                    message += "You beat " + info[0] + " (" + (int)Math.floor(Integer.parseInt(info[1]) / 60) + " minutes and " + (Integer.parseInt(info[1]) % 60) + " seconds)\n\n";
                message += "What is your name? (for the highscore list)";
                
                String name = JOptionPane.showInputDialog(this, message, "You won the game!", JOptionPane.PLAIN_MESSAGE);

                if (info[0] != null || info[1] != null)
                {
                    String prevLine = name.replaceAll("\t", "") + "\t" + time;
                    for (; h < lines.length; h++)
                    {
                        String line = lines[h];
                        lines[h] = prevLine;
                        prevLine = line;
                    }
                }
                else
                {
                    lines[h] = name + "\t" + time + "\n";
                }

                try
                {
                    if (!f.exists())
                        f.createNewFile();

                    BufferedWriter writer = new BufferedWriter(new FileWriter(f));


                    for (int i = 0; i < lines.length; i++)
                    {
                        writer.write(lines[i] + "\n");
                    }

                    writer.flush();
                    writer.close();
                }
                catch (Exception exc) {  }
            }
            else
            {
                JOptionPane.showMessageDialog(this, "You have won the game!\nIt took only " + (int)Math.floor(time / 60) + " minutes and " + (time % 60) + " seconds.");
            }

            // Start new game
            if (type instanceof Klondike)
                ((Klondike)type).newGame();
            if (type instanceof Freecell)
                ((Freecell)type).newGame();
        }
    }

    public class SolitaireFrameActionListener implements ActionListener
    {
        /**
         * Checks for the Menu Item selected and fills string with the object name
         * for debugging purposes name is displayed in console once selected
         *
         * @param e <b>ActionEvent</b>
         */
        public void actionPerformed(ActionEvent e)
        {
            SolitaireType type = new SolitaireType();
            JMenuItem source = (JMenuItem)(e.getSource());
            String menuSelected = source.getName();

            // New game pressed
            if (menuSelected.endsWith("game"))
            {
                System.out.println("Game Menu Selected : " + menuSelected + "\n");
                for (int i = 0; i < SolitaireFrame.this.solitaireTypes.length; i++)
                {
                    SolitaireFrame.this.solitaireTypes[i].setVisible(false);
                    String gameName = menuSelected.replaceAll("game", "");

                    if (SolitaireFrame.this.solitaireTypes[i] instanceof Klondike)
                    {
                        if (((Klondike)SolitaireFrame.this.solitaireTypes[i]).name.compareTo(gameName) == 0)
                        {
                            ((Klondike)SolitaireFrame.this.solitaireTypes[i]).setVisible(true);
                            ((Klondike)SolitaireFrame.this.solitaireTypes[i]).newGame();
                            Insets insets = SolitaireFrame.this.con.getInsets();
                            SolitaireFrame.this.setSize(insets.left + insets.right + ((Klondike)SolitaireFrame.this.solitaireTypes[i]).getWidth() + 30,
                                    insets.top + insets.bottom + ((Klondike)SolitaireFrame.this.solitaireTypes[i]).getHeight() + 30);

                            SolitaireFrame.this.setMaximumSize(new Dimension(SolitaireFrame.this.getWidth(), SolitaireFrame.this.getHeight()));
                            SolitaireFrame.this.setMinimumSize(new Dimension(SolitaireFrame.this.getWidth(), SolitaireFrame.this.getHeight()));
                        }
                    }
                    else if (SolitaireFrame.this.solitaireTypes[i] instanceof Freecell)
                    {
                        if (((Freecell)SolitaireFrame.this.solitaireTypes[i]).name.compareTo(gameName) == 0)
                        {
                            ((Freecell)SolitaireFrame.this.solitaireTypes[i]).setVisible(true);
                            ((Freecell)SolitaireFrame.this.solitaireTypes[i]).newGame();
                            Insets insets = SolitaireFrame.this.con.getInsets();
                            SolitaireFrame.this.setSize(insets.left + insets.right + ((Freecell)SolitaireFrame.this.solitaireTypes[i]).getWidth() + 30,
                                    insets.top + insets.bottom + ((Freecell)SolitaireFrame.this.solitaireTypes[i]).getHeight() + 30);

                            SolitaireFrame.this.setMaximumSize(new Dimension(SolitaireFrame.this.getWidth(), SolitaireFrame.this.getHeight()));
                            SolitaireFrame.this.setMinimumSize(new Dimension(SolitaireFrame.this.getWidth(), SolitaireFrame.this.getHeight()));
                        }
                    }
                    
                }
            }
            // Load game pressed
            else if (menuSelected.endsWith("load"))
            {
                System.out.println("Game Menu Selected : " + menuSelected + "\n");
                for (int i = 0; i < SolitaireFrame.this.solitaireTypes.length; i++)
                {
                    SolitaireFrame.this.solitaireTypes[i].setVisible(false);
                    String gameName = menuSelected.replaceAll("load", "");

                    if (SolitaireFrame.this.solitaireTypes[i] instanceof Klondike)
                    {
                        if (((Klondike)SolitaireFrame.this.solitaireTypes[i]).name.compareTo(gameName) == 0)
                        {
                            ((Klondike)SolitaireFrame.this.solitaireTypes[i]).setVisible(true);
                            ((Klondike)SolitaireFrame.this.solitaireTypes[i]).loadGame();
                            Insets insets = SolitaireFrame.this.con.getInsets();
                            SolitaireFrame.this.setSize(insets.left + insets.right + ((Klondike)SolitaireFrame.this.solitaireTypes[i]).getWidth() + 30,
                                    insets.top + insets.bottom + ((Klondike)SolitaireFrame.this.solitaireTypes[i]).getHeight() + 30);

                            SolitaireFrame.this.setMaximumSize(new Dimension(SolitaireFrame.this.getWidth(), SolitaireFrame.this.getHeight()));
                            SolitaireFrame.this.setMinimumSize(new Dimension(SolitaireFrame.this.getWidth(), SolitaireFrame.this.getHeight()));
                        }
                    }
                    else if (SolitaireFrame.this.solitaireTypes[i] instanceof Freecell)
                    {
                        if (((Freecell)SolitaireFrame.this.solitaireTypes[i]).name.compareTo(gameName) == 0)
                        {
                            ((Freecell)SolitaireFrame.this.solitaireTypes[i]).setVisible(true);
                            ((Freecell)SolitaireFrame.this.solitaireTypes[i]).loadGame();
                            Insets insets = SolitaireFrame.this.con.getInsets();
                            SolitaireFrame.this.setSize(insets.left + insets.right + ((Freecell)SolitaireFrame.this.solitaireTypes[i]).getWidth() + 30,
                                    insets.top + insets.bottom + ((Freecell)SolitaireFrame.this.solitaireTypes[i]).getHeight() + 30);

                            SolitaireFrame.this.setMaximumSize(new Dimension(SolitaireFrame.this.getWidth(), SolitaireFrame.this.getHeight()));
                            SolitaireFrame.this.setMinimumSize(new Dimension(SolitaireFrame.this.getWidth(), SolitaireFrame.this.getHeight()));
                        }
                    }
                   
                }
            }
            // Rules pressed
            else if (menuSelected.endsWith("rules"))
            {
                System.out.print("Rule Call " + menuSelected + "\n");

                String rules = "";
                try
                {
                    BufferedReader reader = new BufferedReader(new FileReader(new File(System.getProperty("user.dir") + "\\" + menuSelected + ".txt")));

                    String line = null;
                    while ((line = reader.readLine()) != null)
                    {
                        rules += line + "\n";
                    }
                }
                catch (FileNotFoundException exc) {  }
                catch (IOException exc) {  }

                JOptionPane.showMessageDialog(SolitaireFrame.this, rules, "Rules for " + menuSelected.replaceAll("rules", ""), JOptionPane.PLAIN_MESSAGE);
            }
            // Highscore pressed
            else if (menuSelected.endsWith("high"))
            {
                System.out.print("Highscore " + menuSelected + "\n");

                String highscores = "";
                try
                {
                    BufferedReader reader = new BufferedReader(new FileReader(new File(System.getProperty("user.dir") + "\\" + menuSelected + ".txt")));

                    String line = null;
                    int c = 1;
                    while ((line = reader.readLine()) != null)
                    {
                        if (line.contains("\t"))
                        {
                            String[] info = line.split("\t");
                            int time = Integer.parseInt(info[1]);
                            highscores += c + ". " + info[0] + " got " + (int)Math.floor(time / 60) + " minutes " + (time % 60) + " seconds. " + "\n";

                            c++;
                        }
                    }
                }
                catch (FileNotFoundException exc) {  }
                catch (IOException exc) {  }

                if (highscores.compareTo("") == 0)
                {
                    highscores = "There haven't been any highscores yet!";
                }

                JOptionPane.showMessageDialog(SolitaireFrame.this, highscores, "Rules for " + menuSelected.replaceAll("high", ""), JOptionPane.PLAIN_MESSAGE);
            }
            // Show hint
            else if (menuSelected.compareTo("hint") == 0)
            {
                for (int i = 0; i < SolitaireFrame.this.solitaireTypes.length; i++)
                {
                    if (SolitaireFrame.this.solitaireTypes[i].isVisible())
                    {
                        if (SolitaireFrame.this.solitaireTypes[i] instanceof Klondike)
                            ((Klondike)SolitaireFrame.this.solitaireTypes[i]).showHint();
                        if (SolitaireFrame.this.solitaireTypes[i] instanceof Freecell)
                            ((Freecell)SolitaireFrame.this.solitaireTypes[i]).showHint();
                    }
                }
            }
            // Show about box
            else if (menuSelected.compareTo("about") == 0)
            {
                JOptionPane.showMessageDialog(SolitaireFrame.this,
                        "Made by the A-Team:\n* Gylfi Bergsveinsson\n* Sveinn Ernstsson\n* Viktor Brynjarsson",
                        "About this",
                        JOptionPane.PLAIN_MESSAGE);
            }
        }
    }
}
